﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Gmantis.Zip
{
    public class ZipEntryCollection : List<ZipEntry>
    {
        // Fields
        private ZipFile _owner;

        // Methods
        internal ZipEntryCollection(ZipFile owner)
        {
            this._owner = owner;
        }

        public void Add(string fileName)
        {
            this.Add(fileName, 0);
        }

        public void Add(string[] fileNames)
        {
            foreach (string str in fileNames)
            {
                this.Add(str, 0);
            }
        }

        public void Add(Stream stream, string entryName)
        {
            DateTime now = DateTime.Now;
            this.Add(stream, entryName, now);
        }

        public void Add(string fileName, int pathLevels)
        {
            string entryName = TrimPath(fileName, pathLevels);
            this.Add(fileName, entryName);
        }

        public void Add(string fileName, string entryName)
        {
            DateTime dateTime = ((fileName != null) && (File.Exists(fileName) || Directory.Exists(fileName))) ? File.GetLastWriteTime(fileName) : DateTime.Now;
            this.Add(fileName, entryName, dateTime);
        }

        public void Add(Stream stream, string entryName, DateTime dateTime)
        {
            this._owner.Add(stream, entryName, dateTime);
        }

        public void Add(string fileName, string entryName, DateTime dateTime)
        {
            if (string.Equals(fileName, this._owner.FileName, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException(StringTables.GetString("Can't add a zip file to itself."));
            }
            bool flag = File.Exists(fileName);
            bool flag2 = !flag && Directory.Exists(fileName);
            if (!flag && !flag2)
            {
                throw new FileNotFoundException(string.Format(StringTables.GetString("File not found: '{0}'."), fileName));
            }
            this._owner.Add(fileName, entryName, dateTime);
        }

        public bool Contains(string name)
        {
            return (this.IndexOf(name) >= 0);
        }

        public void Extract(int index)
        {
            string destFileName = (this._owner.FileName.Length > 0) ? Path.GetDirectoryName(this._owner.FileName) : string.Empty;
            if (destFileName.Length > 0)
            {
                destFileName = destFileName + Path.DirectorySeparatorChar;
            }
            destFileName = destFileName + Path.GetFileName(this._owner.Entries[index].FileName);
            this.Extract(index, destFileName);
        }

        public void Extract(string entryName)
        {
            this.Extract(this.IndexOf(entryName));
        }

        public void Extract(int index, string destFileName)
        {
            if (string.Equals(destFileName, this._owner.FileName, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException(StringTables.GetString("Can't extract entry over parent zip file."), destFileName);
            }
            if ((index < 0) || (index >= base.Count))
            {
                throw new IndexOutOfRangeException(StringTables.GetString("Invalid index or entry name."));
            }
            this._owner.Extract(index, destFileName);
        }

        public void Extract(string entryName, string destFileName)
        {
            this.Extract(this.IndexOf(entryName), destFileName);
        }

        public int IndexOf(string name)
        {
            for (int i = 0; i < base.Count; i++)
            {
                string fileName = base[i].FileName;
                if (string.Equals(name, fileName, StringComparison.OrdinalIgnoreCase))
                {
                    return i;
                }
            }
            return -1;
        }

        public Stream OpenWriter(string entryName, bool useMemory)
        {
            return this._owner.OpenWriter(entryName, DateTime.Now, useMemory);
        }

        public Stream OpenWriter(string entryName, DateTime dateTime, bool useMemory)
        {
            return this._owner.OpenWriter(entryName, dateTime, useMemory);
        }

        public void Remove(int index)
        {
            this._owner.Remove(index);
        }

        public void Remove(string fileName)
        {
            this.Remove(this.IndexOf(fileName));
        }

        public void Remove(int[] indices)
        {
            this._owner.Remove(indices);
        }

        public void Remove(string[] entryNames)
        {
            int[] indices = new int[entryNames.Length];
            for (int i = 0; i < entryNames.Length; i++)
            {
                indices[i] = this.IndexOf(entryNames[i]);
            }
            this.Remove(indices);
        }

        internal static string TrimPath(string fileName, int pathLevels)
        {
            string str = Path.GetFileName(fileName);
            DirectoryInfo parent = new DirectoryInfo(fileName);
            for (int i = 0; i < pathLevels; i++)
            {
                str = string.Format("{0}{1}{2}", parent.Parent.Name, Path.DirectorySeparatorChar, str);
                parent = parent.Parent;
            }
            return str;
        }

        // Properties
        public ZipEntry this[string name]
        {
            get
            {
                int index = this.IndexOf(name);
                if (index >= 0)
                {
                    return base[index];
                }
                return null;
            }
        }
    }
}
